package com.un.ebs.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.un.ebs.core.exception.BusinessException;
import com.un.ebs.product.domain.Product;
import com.un.ebs.product.domain.ProductClass;
import com.un.ebs.product.dto.ProductClassAddDto;
import com.un.ebs.product.dto.ProductClassUpdateDto;
import com.un.ebs.product.mapper.ProductClassMapper;
import com.un.ebs.product.mapper.ProductMapper;
import com.un.ebs.product.service.ProductClassService;
import com.un.ebs.sys.dto.ObjectParentAndIndexChangeDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author liubo
 * @since 2019-09-16
 */
@Service
public class ProductClassServiceImpl extends ServiceImpl<ProductClassMapper, ProductClass> implements ProductClassService {

    @Autowired
    private ProductMapper productMapper;

    @CacheEvict(cacheNames = "product_class", allEntries = true)
    @Override
    public void add(ProductClassAddDto req) {
        List<ProductClassAddDto> list = new ArrayList<>();
        list.add(req);
        add(list);
    }

    @Transactional
    @CacheEvict(cacheNames = {"product_class"}, allEntries = true)
    @Override
    public void add(List<ProductClassAddDto> req) {


        for (ProductClassAddDto reqObj : req) {
            LambdaQueryWrapper<ProductClass> lq = Wrappers.lambdaQuery();
            lq.eq(ProductClass::getCode, reqObj.getCode());
            if (baseMapper.selectCount(lq) > 0) {
                throw new BusinessException(String.format("品类编码 %s 不能重复。", reqObj.getCode()));
            }

            ProductClass obj = new ProductClass();
            obj.setName(reqObj.getName());
            obj.setCode(reqObj.getCode());
            obj.setIsDelete(false);
            obj.setIsNameInclude(reqObj.getIsNameInclude());
            obj.setIsInheritAttr(reqObj.getIsInheritAttr());
            obj.setParentId(reqObj.getParentId());
            if (StringUtils.isEmpty(reqObj.getParentId())) {
                obj.setSort(getBaseMapper().maxSort());
            } else {
                ProductClass parent = queryById(reqObj.getParentId());
                obj.setSort(getBaseMapper().maxSortByParentId(reqObj.getParentId()));
            }
            obj.insert();
        }
    }

    @CacheEvict(cacheNames = {"product_class", "spu_attr_value"}, allEntries = true)
    @Override
    public void update(ProductClassUpdateDto req) {
        ProductClass obj = getById(req.getId());
        obj.setName(req.getName());
        obj.setCode(req.getCode());
        obj.setIsNameInclude(req.getIsNameInclude());
        obj.setIsInheritAttr(req.getIsInheritAttr());
        obj.setParentId(req.getParentId());
        obj.updateById();
    }

    //@Cacheable(cacheNames = "product_class", key = "#id", unless = "#result == null")
    @Override
    public ProductClass queryById(String id) {
        return getBaseMapper().selectById(id);
    }

    @CacheEvict(cacheNames = "product_class")
    @Override
    public void changeParent(String id, String parentId) {
        ProductClass obj = getById(id);
        obj.setParentId(parentId);
        getBaseMapper().updateById(obj);
    }

    @CacheEvict(cacheNames = "product_class", allEntries = true)
    @Transactional
    @Override
    public void changeNode(List<ObjectParentAndIndexChangeDto> nodes) {
        for (ObjectParentAndIndexChangeDto node : nodes) {
            ProductClass productClass = baseMapper.selectById(node.getId());
            productClass.setParentId(node.getParentId());
            productClass.setSort(node.getIndex());
            productClass.updateById();
        }
    }

    @Cacheable(cacheNames = "product_class", key = "root")
    @Override
    public List<ProductClass> queryParent() {
        QueryWrapper<ProductClass> wrapper = Wrappers.query();
        wrapper.isNull("parent_id");
        return getBaseMapper().selectList(wrapper);
    }

    @Override
    public List<ProductClass> queryByParentId(String parentId) {
        QueryWrapper<ProductClass> wrapper = Wrappers.query();
        wrapper.eq("parent_id", parentId);
        return getBaseMapper().selectList(wrapper);
    }

    @Override
    public IPage<ProductClass> queryPageByParentId(String parentId, int pageSize, int pageIndex) {
        Page<ProductClass> page = new Page<>(pageIndex, pageSize);
        QueryWrapper<ProductClass> wrapper = Wrappers.query();
        wrapper.eq("parent_id", parentId);
        return getBaseMapper().selectPage(page, wrapper);
    }

    @Override
    public List<String> queryParentIds(String classId) {
        List<String> result = new ArrayList<>();
        LambdaQueryWrapper<ProductClass> lq = Wrappers.lambdaQuery();
        lq.eq(ProductClass::getId, classId);
        ProductClass obj = baseMapper.selectOne(lq);
        if (obj == null) {
            return null;
        }
        result.add(classId);

        if (!com.un.ebs.core.util.StringUtils.isNullOrEmpty(obj.getParentId())) {
            if (obj.getIsInheritAttr()) {
                result.addAll(queryParentIds(obj.getParentId()));
            }
        }
        return result;
    }

    @CacheEvict(cacheNames = "product_class", allEntries = true)
    @Override
    public void changeSort(String id, int index) {
        ProductClass obj = getById(id);
        obj.setSort(index);
        getBaseMapper().updateById(obj);
    }

    @CacheEvict(cacheNames = "product_class", allEntries = true)
    @Override
    public void delete(String id) {
        LambdaQueryWrapper<Product> lq = Wrappers.lambdaQuery();
        lq.eq(Product::getClassId, id);
        lq.eq(Product::getIsDelete, false);
        long cnt = productMapper.selectCount(lq);
        if (cnt > 0) {
            throw new BusinessException("当前类别下还有 " + cnt + " 笔商品没有删除，请先删除商品后再执行此操作。");
        }
        getBaseMapper().deleteById(id);
    }

}